#include "stdlib.hpp"
#include <purewell/file.hpp>
#include <purewell/fileutil.hpp>

namespace purewell
{

PWFileUtil& gPWFileUtil(PWFileUtil::getInstance());

PWFileUtil::PWFileUtil()
{
}

PWFileUtil::~PWFileUtil()
{
}

PWFileUtil&
PWFileUtil::getInstance(void)
{
	static PWFileUtil inst;
	return inst;
}

bool
PWFileUtil::setModeAsync(PWFile& file, bool async) const
{
#ifndef WIN32
	const int arg(async);
	return -1 != ::ioctl(file.getHandle(), FIOASYNC, &arg);
#else
	return file.setModeAsync(async);
#endif
}

bool
PWFileUtil::getModeAsync(const PWFile& file) const
{
#ifndef WIN32
	int fd(file.getHandle());
	int flags( fcntl(fd, F_GETFL) );
	if ( -1 == flags ) return false;

	return ( 0 != (flags & O_ASYNC) );
#else
	bool res;
	if (file.getModeAsync(res)) return res;
	return false;
#endif
}

bool
PWFileUtil::setModeBlock(PWFile& file, bool block) const
{
#ifndef WIN32
	const int arg(!block);
	return -1 != ::ioctl(file.getHandle(), FIONBIO, &arg);
#else
	return file.setModeBlock(block);
#endif

#if 0
	int fd(file.getHandle());
	int flags( fcntl(fd, F_GETFL) );
	if ( -1 == flags ) return false;

	if ( block ) flags &= O_NONBLOCK;
	else flags |= O_NONBLOCK;

	return -1 != fcntl(fd, F_SETFL, flags);
#endif
}

bool
PWFileUtil::getModeBlock(const PWFile& file) const
{
#ifndef WIN32
	int fd(file.getHandle());
	int flags( fcntl(fd, F_GETFL) );
	if ( -1 == flags ) return false;

	return ( 0 == (flags & O_NONBLOCK) );
#else
	bool res;
	if (file.getModeBlock(res)) return res;
	return false;
#endif
}

bool
PWFileUtil::duplicate(PWFile& dst, const PWFile& src) const
{
	const int dfd(dup(src.getHandle()));
	if ( -1 == dfd ) return false;

	const bool res(dst.attach(dfd));
	if ( !res )
	{
		::close(dfd);
	}

	return res;
}

bool
PWFileUtil::duplicate(PWFile& dst, const PWFile& src, int newfd) const
{
	const int dfd(dup2(src.getHandle(), newfd));
	if ( -1 == dfd ) return false;

	const bool res(dst.attach(dfd));
	if ( !res )
	{
		::close(dfd);
	}

	return res;
}

};

